/**
 * 文件：MatchingServiceImpl.java
 * 作者：赵子樵
 * 完成度：完成
 * 最后修改日期：2023-7-9 02:00
 */

package com.gomokult.service.impl;

import java.util.*;
import com.gomokult.entity.MatchingRequest;
import com.gomokult.service.MatchingService;

/**
 * 对局匹配服务（MatchingService）的实现类。
 * @author 赵子樵
 */
public class MatchingServiceImpl implements MatchingService {
	@SuppressWarnings("unchecked")
	private final Queue<MatchingRequest>[] requestQueues = new Queue[8];	// 表示八个不同分级的用户请求队列；
	private final Set<Integer> emergencyRequestIDs = new HashSet<>();		// 用于存储即将超时的匹配请求；
	private final Map<Integer, String> matchedMapping = new TreeMap<>();	// 用于存储用户的匹配结果；

	// 将用户"firstUserID"与"secondUserID"进行配对：
	private void makeMatch(Integer firstUserID, Integer secondUserID) {
		double rand = Math.random();
		matchedMapping.put(firstUserID, (rand < 0.5 ? "B#" : "W#") + secondUserID);
		matchedMapping.put(secondUserID, (rand < 0.5 ? "W#" : "B#") + firstUserID);
		emergencyRequestIDs.remove(firstUserID);
		emergencyRequestIDs.remove(secondUserID);
	}
	// 更新请求队列与匹配映射表：
	private void updateMapping() {
		long currentTimestamp = new Date().getTime();
		for (Queue<MatchingRequest> requestQueue : requestQueues) {
			while (requestQueue.size() > 0 && currentTimestamp - requestQueue.peek().getTimestamp() > 30 * 1000)
				matchedMapping.put(requestQueue.poll().getUserID(), "?#-1");
			if (requestQueue.size() >= 2)
				makeMatch(requestQueue.poll().getUserID(), requestQueue.poll().getUserID());
			else if (requestQueue.size() > 0 && currentTimestamp - requestQueue.peek().getTimestamp() > 20 * 1000)
				emergencyRequestIDs.add(requestQueue.peek().getUserID());
		}
		while (emergencyRequestIDs.size() >= 2) {
			Iterator<Integer> iterator = emergencyRequestIDs.iterator();
			makeMatch(iterator.next(), iterator.next());
		}
	}

	// 接口方法实现：
	@Override
	public synchronized void requestMatching(MatchingRequest request, int level) {
		requestQueues[level].add(request);
		updateMapping();
	}
	@Override
	public synchronized void clearRequest(int userID) {
		for (Queue<MatchingRequest> requestQueue : requestQueues)
			((LinkedList<MatchingRequest>)requestQueue).removeIf(request -> request.getUserID() == userID);
		emergencyRequestIDs.remove(userID);
		matchedMapping.remove(userID);
	}
	@Override
	public synchronized void cancelMatching(int userID) {
		clearRequest(userID);
		matchedMapping.put(userID, "?#-1");
	}
	@Override
	public synchronized String pollMatchingResult(int userID) {
		String matchedUserInfo = matchedMapping.get(userID);
		if (matchedUserInfo != null)
			clearRequest(userID);
		return matchedUserInfo == null ? "?#0" : matchedUserInfo;
	}

	// 构造单例对象，并为其提供访问器：
	private MatchingServiceImpl() {
		for (int i = 0; i < 8; ++i)
			requestQueues[i] = new LinkedList<>();
		new Timer().scheduleAtFixedRate(new TimerTask() {
			@Override
			public void run() { updateMapping(); }
		}, 0, 1000);
	}
	private static final MatchingServiceImpl singleton = new MatchingServiceImpl();
	public static MatchingServiceImpl getSingleton() { return singleton; }
}
